package de.gameduell.framework.gui.builder {

	/**
	 * @author avar
	 */
	import de.gameduell.framework.debug.Debug;
	import de.gameduell.framework.util.HashMap;
	import de.gameduell.framework.util.Library;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.system.ApplicationDomain;

	public class DisplayObjectList{

		private  var _id:String ;
		private  var _defaultIdIndex:uint;
		private var _domain:ApplicationDomain;
		private var _library:Library;
		private var _displayObjects:HashMap;
		private var _rootContainer:Sprite;
		private var _data:XML;

		public function DisplayObjectList(data:XML, domain : ApplicationDomain = null) {
			_domain = domain;
			_library = Library.getInstance();
			_displayObjects = new HashMap();
			_defaultIdIndex = 0;
			_id = data.@id;
			_data = data;
			_rootContainer = new Sprite();
			parseLayers(_data.children());
		}
		
		public function get id():String {
			return _id;
		}

		public function get displayObjects():HashMap {
			return _displayObjects;
		}
		
		public function getDisplayObjectById(id:String):DisplayObject {
			return _displayObjects.get(id) as DisplayObject;
		}

		public function attachTo(container:Sprite):void {
			if(_rootContainer == container) {
				return;
			}

			while(_rootContainer.numChildren > 0) {
				container.addChild(_rootContainer.getChildAt(0));
			}
			_rootContainer = container;
		}

		public function reset():void {
			for (var i:uint = 0 ;i < _displayObjects.values.length; i++ ) {
				_displayObjects.values[i].parent.removeChild(_displayObjects.values[i]);
			}

			_displayObjects = new HashMap();
			_defaultIdIndex = 0;
			_rootContainer = new Sprite();
			parseLayers(_data.children());
		}

		private function parseLayers(layerList:XMLList):Vector.<DisplayObject> {
			var displayObjects:Vector.<DisplayObject> = new Vector.<DisplayObject>();
			for (var i:uint = 0;i < layerList.length(); i++) {
				var layerNode:XML = layerList[i];
				var parent:DisplayObject; 
				parent = parseChild(layerNode);
				checkChild(layerNode, parent);
				_rootContainer.addChild(parent);
			}
			return displayObjects;
		}

		private function checkChild(node:XML, parent:DisplayObject = null):void {
			if( node.children().length() > 0 && parent is DisplayObjectContainer ) {
				parseChildren(node, DisplayObjectContainer(parent));
			}
		}

		private function parseChildren(node:XML, parent:DisplayObjectContainer):void {
			var length:uint = node.children().length();
			for (var i:uint = 0;i < length; i++) {
				var childNode:XML = node.children()[i];
				var child:DisplayObject = parseChild(childNode);
				parent.addChild(child);
				checkChild(childNode, child);
			}
		}

		private function parseChild( childNode:XML ):DisplayObject {
			var nodeType:String = childNode.name();
			switch(nodeType) {
				case "bitmap":
					return createBitmap(childNode);
					break;
				case "sprite": 
					return createSprite(childNode); 
					break; 
			}
			return null;
		} 

		private function createBitmap( node:XML ):Bitmap {
			var bitmap:Bitmap;
			try { 
				var id:String = node.@id ;
				if(id == "") {
					id = _id + _defaultIdIndex.toString();
					_defaultIdIndex++;
				}
				var name:String = node.@varName;
				var width:Number = node.@width != "" ? Number(node.@width) : 0;
				var height:Number = node.@height != "" ? Number(node.@height) : 0 ;
				var x:Number = node.@x != "" ? Number(node.@x) : 0;
				var y:Number = node.@y != "" ? Number(node.@y) : 0;
				var symbol:String = node.@symbol;
				var smoothing:Boolean = node.@smoothing == "true" ? true : false;
				var cacheSensitive:Boolean = node.@cacheSensitive == "true" ? true : false;
				var bitmapData:BitmapData = _library.createBitmapData(symbol, width, height, _domain);
				bitmap = new Bitmap(bitmapData, PixelSnapping.NEVER, smoothing);
				bitmap.x = x;
				bitmap.y = y;
				bitmap.width = width;
				bitmap.height = height;

				bitmap.name = name;
				bitmap.cacheAsBitmap = cacheSensitive;
			} catch( e:Error ) {
				Debug.trace("Bitmap creating failed in StaticRenderer.");
			}
			_displayObjects.put(id, bitmap);
			return bitmap;
		}

		private function createSprite( node:XML ):Sprite {
			var sprite:Sprite;
			try { 
				var id:String = node.@id ;
				if(id == "") {
					Debug.trace("Static render has empty id");
					id = _id + _defaultIdIndex.toString();
					_defaultIdIndex++;
				}
				var symbol:String = node.@symbol;
				var name:String = node.@varName;
				var width:Number = node.@width != "" ? Number(node.@width) : 0;
				var height:Number = node.@height != "" ? Number(node.@height) : 0;
				var x:Number = node.@x != "" ? Number(node.@x) : 0;
				var y:Number = node.@y != "" ? Number(node.@y) : 0;
				var cacheSensitive:Boolean = node.@cacheSensitive == "true" ? true : false;
				if( symbol == "") {
					sprite = new Sprite();
				} else {
					sprite = _library.createSprite(symbol, _domain);
					sprite.width = width;
					sprite.height = height; 
				}
				sprite.name = name;
				sprite.x = x;
				sprite.y = y;
				sprite.cacheAsBitmap = cacheSensitive;
			} catch( e:Error ) {
				Debug.trace("Sprite creating failed in StaticRenderer.");
			}
			
			_displayObjects.put(id, sprite);
			return sprite;
		}
	}
}
